/**
 * 
 */
package org.vsg.stock.basic.service;

import java.text.DecimalFormat;
import java.util.Map;
import java.util.WeakHashMap;

import org.vsg.stock.core.domain.StockDailyKLine;

/**
 * @author Bill Vison
 *
 */
public class StockBusinessHelper {
	
	/**
	 * using StockBusinessHelperManager.checkBlurLimited
	 * @deprecated
	 * @param price
	 * @param diff
	 * @return
	 */
	public static boolean checkDiffScope(double price , double diff) {
		
		double compValue = (diff * 100 )/ price ;
		
		
		// --- stock with low price will be set the higher of the radio than high price
		boolean canMerge;
		if ( price <= 5) {
			canMerge = compValue < 1.0;
		}
		else if ( price <= 6 && price > 5) {
			canMerge = compValue < 0.6;
		}
		else if (price > 6 && price <= 10) {
			canMerge = compValue < 0.5;
		}
		else {
			// different between 0 to 1
			canMerge = compValue < 0.4 ;
			
		}
		return canMerge;
	}
	
	public static final short MAX_DIFF = 1;
	
	public static final short MIN_DIFF = 0 ;
	
	/**
	 * @deprecated
	 * get diff abs price value , please use StockBusinessHelperManager.getStockBlurLimitedPrice
	 * @param price
	 * @param type
	 * @return
	 */
	public static double getDiffRelativedPrice(double price, short type) {

		double diff = 0;
		double maxPrice = 0;
		double minPrice = 0;
		if ( price <= 6) {
			diff = price * 0.007;
		}
		else if (price > 6 && price <= 10) {
			diff = price * 0.005;
		}
		else {
			// different between 0 to 1
			diff = price * 0.003;
		}		
		maxPrice = price + diff;
		minPrice = price - diff;
		
		if (type == MAX_DIFF) {
			return maxPrice;
		} else {
			return minPrice;
		}
		
	}
	
	private static DecimalFormat numberF = new DecimalFormat("0");
	public static boolean checkIsIntegerPrice(double price) {
		boolean isIntegerPrice = false;
		
		String value = numberF.format( price * 100 );
		if (value.endsWith("0") || value.endsWith("5") ) {
			isIntegerPrice = true;
		}
		return isIntegerPrice;
	}
	
	public static Map<Double , String> mergeToPriceMap(StockDailyKLine kline) {
		double mainTopPrice = kline.getOpen() > kline.getClose() ? kline.getOpen() : kline.getClose();
		double mainButtonPrice = kline.getClose() < kline.getOpen() ? kline.getClose() : kline.getOpen();
		
		
		Map<Double,String> mergePrice = new WeakHashMap<Double,String>();
		
		// --- difference between high , close , open , low ---
		double diffInHT = Math.abs( kline.getHigh() - mainTopPrice );
		double diffInHB = Math.abs( kline.getHigh() - mainButtonPrice );
		double diffInLB = Math.abs( kline.getLow() - mainButtonPrice );
		double diffInLT = Math.abs( kline.getLow() - mainTopPrice );
		double diffInOC = Math.abs( kline.getOpen() - kline.getClose() );
		
		boolean needRecordHigh = true;
		boolean needRecordOpen = true;
		boolean needRecordClose = true;
		boolean needRecordLow = true;
		
		// --- high check ----
		if (StockBusinessHelper.checkDiffScope(kline.getHigh() , diffInHB) ) {
			needRecordOpen = false;
			needRecordClose = false;
		}
		else if ( StockBusinessHelper.checkDiffScope(kline.getHigh() , diffInHT) ) {
			if ( kline.getClose() > kline.getOpen() ) {
				needRecordClose = false;
			} else {
				needRecordOpen = false;
			}
		}
		
		// --- low check ---
		if ( StockBusinessHelper.checkDiffScope(kline.getLow() , diffInLT) ) {
			needRecordOpen = false;
			needRecordClose = false;
		}
		else if ( StockBusinessHelper.checkDiffScope(kline.getLow() , diffInLB) ) {
			if ( kline.getClose() < kline.getOpen() ) {
				needRecordClose = false;
			} else {
				needRecordOpen = false;
			}
		}
		
		// --- close & open check ----
		if ( needRecordOpen && needRecordOpen
				&& StockBusinessHelper.checkDiffScope(kline.getOpen() , diffInOC) ) {
			needRecordClose = false;
		}
		
		// --- set the merge price ---
		if (needRecordHigh) {
			mergePrice.put( kline.getHigh() , "H");
		}
		
		if (needRecordOpen) {
			mergePrice.put( kline.getOpen(), "O");
		}
	
		if (needRecordClose) {
			mergePrice.put( kline.getClose(), "C");
		}

		if (needRecordLow) {
			mergePrice.put( kline.getLow(), "L");
		}

		
		return mergePrice;
	}
		

}
